package org.setamv.springcloud.hystrix.raw.command;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;

/**
 * 测试Hystrix命令链式调用时，如果子命令发生超时，触发父命令回退<p>
 * 例如，在银行卡转账的命令TransferAccountCommand中，将依次执行从A账户扣款命令OutcomeCommand、将钱划入B账户的入款命令IncomeCommand
 */
public class ChainedFallbackCommand {

    public static void main(String[] args) {
        HystrixCommand<String> command = new TransferAccountCommand();
        String result = command.execute();
        System.out.println(result);
    }

    /**
     * 转账命令
     */
    public static class TransferAccountCommand extends HystrixCommand<String> {
        public TransferAccountCommand() {
            // 设置超时时间为1秒
            super(Setter
                    .withGroupKey(HystrixCommandGroupKey.Factory.asKey("testGroup"))
                    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(1000)));
        }

        @Override
        protected String run() throws Exception {
            // 这里依次执行从A账户扣款命令OutcomeCommand、将钱划入B账户的入款命令IncomeCommand
            String outcomeResult = new OutcomeCommand().execute();
            String incomeResult = new IncomeCommand().execute();
            return outcomeResult + "\n" + incomeResult;
        }

        @Override
        protected String getFallback() {
            return "transfer account command fall back.";
        }
    }

    /**
     * 扣款命令
     */
    public static class OutcomeCommand extends HystrixCommand<String> {
        public OutcomeCommand() {
            super(HystrixCommandGroupKey.Factory.asKey("testGroup"));
        }

        @Override
        protected String run() throws Exception {
            return "outcome command";
        }

        @Override
        protected String getFallback() {
            return "outcome command fall back.";
        }
    }

    /**
     * 扣款命令。
     * 假设扣款发生超时
     */
    public static class IncomeCommand extends HystrixCommand<String> {
        public IncomeCommand() {
            super(Setter
                    .withGroupKey(HystrixCommandGroupKey.Factory.asKey("testGroup"))
                    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(1000)));
        }

        @Override
        protected String run() throws Exception {
            // 延迟5秒执行，超过超时时间，是的该命令执行失败
            Thread.sleep(5 * 1000);
            return "income command";
        }

        @Override
        protected String getFallback() {
            return "income command fall back.";
        }
    }
}
